﻿using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;

namespace CreatorPackageTools;

public class Program
{
    private const string Version = "V10";

    public static void Main(string[] args)
    {
        var solutionPath = args[0];
        Console.WriteLine("solutionPath: " + solutionPath);

        var guid = Guid.NewGuid().ToString();
        var targetPath = Path.Combine(solutionPath, guid);

        try
        {
            Directory.CreateDirectory(targetPath);
            CopyFolder(
                Path.Combine(solutionPath, "bin"),
                Path.Combine(targetPath, "bin"),
                new[] { ".pdb" },
                null
            );
            CopyFolder(
                Path.Combine(solutionPath, "ForguncyTemplateSecurityProvider"),
                Path.Combine(targetPath, "ForguncyTemplateSecurityProvider"),
                null,
                new[] { "bin", ".vs", "obj" });

            var targetZip = Path.Combine(solutionPath, $"ForguncySecurityProviderBuilder_{Version}.zip");

            if (File.Exists(targetZip))
            {
                File.Delete(targetZip);
            }

            ZipFile.CreateFromDirectory(targetPath, targetZip);
        }
        finally
        {
            Directory.Delete(targetPath, true);
        }
    }

    private static void CopyFolder(string sPath, string dPath, string[] ignoreFiles, string[] ignoreDirs)
    {
        CopyFolder(sPath, dPath, (path, isFile) =>
        {
            if (isFile)
            {
                if (ignoreFiles != null)
                {
                    if (IsMatchIgnoreFile(ignoreFiles, path))
                    {
                        return false;
                    }
                }
            }
            else
            {
                if (ignoreDirs != null)
                {
                    if (ignoreDirs.Contains(Path.GetFileName(path)))
                    {
                        return false;
                    }
                }
            }

            return true;
        });
    }

    private static bool IsMatchIgnoreFile(string[] ignoreFiles, string file)
    {
        if (ignoreFiles == null)
        {
            return false;
        }

        foreach (var ignoreFile in ignoreFiles)
        {
            var fileName = Path.GetFileName(file).ToLower();
            var condition = ignoreFile.ToLower();
            if (condition.StartsWith("."))
            {
                if (fileName.EndsWith(condition))
                {
                    return true;
                }
            }
            else
            {
                if (fileName == condition)
                {
                    return true;
                }
            }
        }

        return false;
    }

    private static void CopyFolder(string sPath, string dPath, Func<string, bool, bool> filter)
    {
        if (!Directory.Exists(sPath))
        {
            return;
        }

        // 创建目的文件夹                  
        if (!Directory.Exists(dPath))
        {
            Directory.CreateDirectory(dPath!);
        }

        var files = GetFiles(sPath);
        Parallel.ForEach(files, file =>
        {
            var targetFileFullName = dPath + Path.DirectorySeparatorChar + Path.GetFileName(file);
            if (filter != null && !filter(file, true))
            {
                return;
            }

            try
            {
                // if target file exists and is readonly.the CopyTo method will throw a unauthorized exception
                File.Copy(file, targetFileFullName, true);
            }
            catch
            {
                // Try again? 有的时候拷贝文件会崩，但是，手工按一下F5就好了，这里尝试再拷贝一次来绕这个Bug，没想到别的好的方案。权且一试，
                // 等找的好方案或者不能修复这个问题在看， 胡森
                File.Copy(file, targetFileFullName, true);
            }
        });

        // 循环子文件夹
        var subDirArray = Directory.GetDirectories(sPath);
        foreach (var subDir in subDirArray)
        {
            if (filter != null && !filter(subDir, false))
            {
                continue;
            }

            CopyFolder(subDir, dPath + Path.DirectorySeparatorChar + Path.GetFileName(subDir), filter);
        }
    }

    private static string[] GetFiles(string path)
    {
        try
        {
            return Directory.GetFiles(path);
        }
        catch
        {
            return Array.Empty<string>();
        }
    }
}